Introduction Section
### Introduction
Western music is usually notated on a five-line staff, on which **notes** are given a **duration** based on symbol type, and **pitch** based on location in the staff. Composers can use proprietary software such as Sibelius or Finale to manipulate a virtual five-line staff through mouse clicks or keyboard gestures. Fans of computer music might instead use music synthesis libraries to programmatically create music in languages such as C++, but such libraries can be unintuitive for musicians unfamiliar with signals and waves.

We propose Music-mike, a compiled, strongly typed, functional programming language, to give users an alternative option in music creation. Music-mike is designed for users to create music based on varied manipulations of short patterns. We owe this idea to Note Hashtag, a previous project completed in COMS W4115. However, unlike Note Hashtag, Music-mike is **modal** rather than **key-based**. Furthermore, lists - treated as the fundamental building block of music - are manipulated with special list operators (syntactic sugar) which create an intuitive interface based on traditional staff notation.

### Design Ethos
The most basic unit in music is a **note**, which can be decomposed into pitch and duration. A simple melody can thus be described as two lists: one list of pitches and another of durations. A **chord** is a collection of notes played simultaneously.

A set of pitches is defined as a **mode**. All modes are subsets of the chromatic scale, which contains all twelve pitch classes used in Western music. Most music constrains the pitches of its notes to a small set of familiar modes, such as the major and minor scales. The sound of a **chord** is very much dependent on the **mode** that its notes come from.

Music-mike is based on the following observations regarding Western music: one, that Western music is fundamentally  **chordal** and **modal**. Two, that Western music is repetitive and manipulative: simple building blocks of music are modified, then repeated multiple times in a piece. Finally, and most importantly, that these simple building blocks can described using lists and altered using a functional paradigm.

Language Tutorial Section

Basics

Let's try defining a variable first:

x = 5;

Now, let's write a function:

def AddFive a = a + 5;

Notice that we don't need to add any type annotations. Type inference handles everything for us.
We can also write polymorphic functions, like the identity function:

def Identity x = x;
y = Identity("Who am I");
Printstr(y);

Function calls require parentheses around arguments, but no commas to separate. For example:

def Add j k = j + k;
sum = Add(4 5);

Note that arithmetic operators do not overload: we cannot pass in an floats to our Add function:

/* This fails! */
wrong = Add(4.5 3);

A Musical Hello World

First we need to define a mode:

/* A major scale */
major = [1 3 5 6 8 10 12 13]; 

A rhythm list is defined with the r:[] constructor:

r1 = r:[s s s s s s e s s s s s s e];

A pitch list is defined with the p:[] constructor:

p1 = p:[1 1 5 5 6 6 5 4 4 3 3 2 2 1];

Now, we can generate a music string with the Synth function, which
takes a pitch list, rhythm list, mode, start node, and channel:

startnote = 50;
s = Synth(p1 r1 major startnote 1);
/* Make_midi outputs a midi file */  
Make_midi(s "twinkle.midi");

And that is twinkle twinkle little star!

LRM Section
Project Plan Section
A. Process
  i. Planning
  Our team met regularly twice a week on Wednesdays to meet with our TA Jacob Graff and
  on Sundays to work together as a team, debrief and set the course for the rest of the week. We used
  our Wednesday meetings as an opportunity to track and gauge our progress and also ask questions about
  difficult problems we came across during the previous week. We also talked about goals and milestones for the next
  Wednesday meeting and talked about any potential problems related to the difficulties of the goals we defined but also
  about any foreseeable road blocks related to tests, projects, other classes etc. that might hinder our progress. We used
  these meetings to make sure our project was progressing but also to shift our timeline to account for future roadblocks and delays.
  ii. Specifications
  We spent the first three weeks deciding the specifications of our language. We all met
  near a piano either in the basement of the dorms or in Lerner and went over intuitive ways
  for musicians to express music. Once we chose how we wanted to abstract notes, pitches, chords, tempos and more, we started
  talking about how to structure our language. We initially chose to do a functional language modelled after OCaml, but as we progressed,
  we realized that for the use cases we were targeting a fully functional language wouldn't give us the kind of ease of use and usage we'd like.
  Our first concrete specifications were the abstractions and then we decided on syntax. Despite having a very concrete definition of specifications
  early on, we still changed specifications as we worked on our language when it was necessary to be able to finish within our timeline.

  iii. Development
  Our team used github issues to define specifications and tasks that needed to be implemented or completed. We used github to help
  with organizing our development. Each of used a separate branch to develop the feature that we were working on and then submitted a pull
  request to the main branch once we thought it was ready. Then, another member of the team would review that request and merge the request. This ensured
  that all the code we pushed had been code reviewed and helped us maintain the quality of our mainline code.

  iv. Testing
  We developed a test suite that tested individual components of the compiler. Every time one of
  us was working on a small component, we first wrote a test for how that component was supposed to work
  once it was finished. When writing In this regard, we used some principles of Test-First Programming to make sure we were preserving
  the functionality of the older features but also ensuring functionality of the new ones. While some of these tests were forward
  looking and failed early-on, the error messages told the developer whether we were making progress towards making these larger full stack
  tests work or if it was failing in whatever module the developer was working on.
B. Programming Style Guide
1. Landin's pseudo law: Treat the indentation of your programs as if it determines the meaning of your programs.
Keep indentation consistent with that of the MicroC code.

2. Keep lines shorter than 80 characters.

3. A function should always fit within one screenful (of about 70 lines), or in exceptional cases two, at the very most three. To go beyond this is unreasonable.

Justification: When a function goes beyond one screenful, it's time to divide it into subproblems and handle them independently. Beyond a screenful, one gets lost in the code. The indentation is not readable and is difficult to keep correct.

4. The change in indentation between successive lines of the program is 2 spaces.

5. Using the tab character (ASCII character 9) is absolutely not recommended. Change your .vimrc if you have tabs.

6. Use underscores instead of Camel case

C. Timeline
Table
Date        Milestone
Jan 29th    First commit to repository
Feb 8th     Project Proposal and White Paper Completed and Submitted
Feb 22      Language Reference Manual Completed and Submitted
Mar 21      Basic Scanner Complete
Mar 26      Basic AST and Parser Complete
Mar 29      Hello World runs
Apr 7       Testing Framework Complete
Apr 23      Final Scanner, Parser and AST Complete

D. Roles and Responsibilities
While we had defined project roles at the beginning of the semester, about
three weeks in the roles became a lot more fluid. Our assigned roles were
Tester, System Architect, Project Manager and Language Guru. Each member was involved
in developing certain functionalities and portions of components. The team frequently worked
together either in-person or teleconference.
Team Member
Husam Abdul-Kafi  Systems Architect Code generation, Testing Architecture
Lakshmi Bodapati  Project Manager   Compiler Front-end, Documentation, Polymorphic Function Typing
Kaitlin Pet       Tester            Pitch and Chord Full Stack Abstraction, Library Linking, Testing Architecture
Harvey Wu         Language Guru     Type Inference, Compiler Front-end

E. Software Development Environment
Our Stack
/list
/l1 Version Control: Git, Github
/l2 Languages: OCaml 4.04.0, C, Bash
/l3 Text Editor: Vim, Sublime Text, Atom
/l4 Operating System: Ubuntu 16.04, Mac OS X, Windows 10
/l5 Virtual Machine: Google Cloud 

F. Project Log
****************COPY FROM GIT WHEN FINISHED****************

Architectural Design Section

B. Scanner (Lakshmi, Husam, Harvey)
Relevant Files: scanner.mll

The scanner is written in Ocamllex and takes the .mike input to the compiler
and tokenizes it into literals, identifiers, operators and keywords. It removes the white space
and block comments. If any character cannot be lexed by the scanner or if
any identifier or literal is not syntactically valid, the scanner throws an error. The tokens
created by the scanner are used by the Parser to create an Abstract Syntax Tree. The scanner is
context sensitive, so uses different pattern matching inside of rhythm and pitch lists.

C. Parser (Husam, Harvey, Kaitlin, Lakshmi)
Relevant Files: parser.mly

The parser is written in Ocamlyacc and takes in a series of tokens. It uses the grammar described
in parser.mly and datatypes defined in ast.ml to generate an Abstract Syntax Tree. In parser.mly, we define
the Music-mike context-free grammar using productions. If the tokens produced by the scanner are successfully
parsed that means that the .mike file is syntactically (though perhaps not semantically) correct.

D. Type Inference (Harvey)
Relevant Files: infer.ml 

The type inference module takes in the untyped AST of expressions and runs Algorithm W (Hindley Milner Type 
Inference).  
Type checking is also done in one swift pass - a list, for example, cannot contain elements of two different
types.
Scope is also handled in this module - a single global map stores variables and their types and thus
typing is dynamic. Variables and functions cannot be redefined. Other semantic checking, such as argument
counts 

E. Semant (Lakshmi, Husam, Harvey)
Relevant Files: semant.ml
The semant module is an extension of type inference, and handles polymorphic functions.
It first finds all the polymorphic functions, then finds all the calls made to these functions and adds in
typed function definitions in place of the dummy type polymorphic functions.

E. The Code Generator (Husam, Kaitlin, Lakshmi)
Relevant Files: codegen.ml

F. The C Libraries (Kaitlin, Lakshmi, Husam)
The synth and make_midi built-in functions were written in C. The C methods convert our rhythm, pitch and other music
structures into absolute pitches, rhythms and chords expressed in the CFugue syntax. We then call an executable we wrote
that takes in an input string and produces a Midi file output using the CFugue libraries. This call to the compiled
CFugue interfacer occurs in the make_midi C method.

Test Plan Section
A. *****************2 examples of source to code******************
B. Test Suites
We wrote tests for every time we implemented a new feature. We also wrote integration tests
to make sure that our modules worked in conjunction with each other. For each test, we also wrote
an expected output file.
C. Test Automation
Our test automation script, testall.sh, runs every test and compares it to the expected output for that test. The testing script is included in the Appendix.

Lessons Learned Section
A. Husam Abdul-Kafi

B. Lakshmi Bodapati

I learned a lot about Git and pull requests and how easily git branches can become
messy, unorganized and complicated tree of merge conflicts. I also learned how to solve those
problems, maybe not in the Git recommended way, but some way of getting a working master branch after
merging in 4+ branches of conflicting code. I also learned a lot about dividing work and maximizing efficiency
when all of us were working together and trying to knock out chunks of the project during our longer weekly meetings. The trickiest
part was dividing up work such that everyone had something to do that wasn't blocked by something someone else had to do and
every task was being worked on by someone who had some idea of what was necessary for successful completion. The coolest thing I
learned was how to write a context-sensitive scanner. I learned the most OCaml while writing the polymorphic function definitions and
call matching in the semant module. I also learned that OCaml is quite frosty and nice.
For future teams, start early, own features not modules and don't be afraid to OCaml it up!

C. Kaitlin Pet

D. Harvey Wu

This was, by far, the largest project of my programming career, and the first one that involved a lot of teamwork.
I learned to communicate often with my team, even if not much progress was being made, if just to touch base and
keep each other interested in the project. Safe to say, I also got to know the ins-and-outs of Git pretty well. 

I had never touched functional programming before this class and I loved the "if it compiles it works" aspect of 
OCaml. By implementing a type inference algorithm I also learned a lot about what makes OCaml tick.

Our group spent too much time early on arguing about syntax and design choices that seemed relatively trivial down 
the road. For future groups: decide on something, and stick to it. Unless it breaks :)


Appendix Section
(*****************Include all code listings**************)
(*****************Include Git log************************)
(*****************Include test scripts********************)
